using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;

public class XEditorHelper
{
    /// <summary>
    /// Draw a distinctly different looking header label
    /// </summary>

    static public bool DrawHeader(string text) { return DrawHeader(text, text, false); }

    /// <summary>
    /// Draw a distinctly different looking header label
    /// </summary>

    static public bool DrawHeader(string text, string key) { return DrawHeader(text, key, false); }

    /// <summary>
    /// Draw a distinctly different looking header label
    /// </summary>

    static public bool DrawHeader(string text, bool forceOn) { return DrawHeader(text, text, forceOn); }

    /// <summary>
    /// Draw a distinctly different looking header label
    /// </summary>

    static public bool DrawHeader(string text, string key, bool forceOn)
    {
        bool state = EditorPrefs.GetBool(key, true);

        GUILayout.Space(3f);
        if (!forceOn && !state) GUI.backgroundColor = new Color(0.8f, 0.8f, 0.8f);
        GUILayout.BeginHorizontal();
        GUILayout.Space(3f);

        GUI.changed = false;
#if UNITY_3_5
            if (state) text = "\u25B2 " + text;
            else text = "\u25BC " + text;
            if (!GUILayout.Toggle(true, text, "dragtab", GUILayout.MinWidth(20f))) state = !state;
#else
        text = "<b><size=11>" + text + "</size></b>";
        if (state) text = "\u25B2 " + text;
        else text = "\u25BC " + text;
        if (!GUILayout.Toggle(true, text, "dragtab", GUILayout.MinWidth(20f))) state = !state;
#endif
        if (GUI.changed) EditorPrefs.SetBool(key, state);

        GUILayout.Space(2f);
        GUILayout.EndHorizontal();
        GUI.backgroundColor = Color.white;
        if (!forceOn && !state) GUILayout.Space(3f);
        return state;
    }

    static public void DrawTitle(string title)
    {
        string text = "<b><size=11>" + title + "</size></b>";
        GUILayout.Label(text, "dragtab", GUILayout.MinWidth(20f));
    }

    /// <summary>
    /// Begin drawing the content area.
    /// </summary>

    static public void BeginContents()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Space(4f);
        EditorGUILayout.BeginHorizontal("box", GUILayout.MinHeight(10f));
        GUILayout.BeginVertical();
        GUILayout.Space(2f);
    }

    /// <summary>
    /// End drawing the content area.
    /// </summary>

    static public void EndContents()
    {
        GUILayout.Space(3f);
        GUILayout.EndVertical();
        EditorGUILayout.EndHorizontal();
        GUILayout.Space(3f);
        GUILayout.EndHorizontal();
        GUILayout.Space(3f);
    }
}

/// <summary>
/// 
/// </summary>
public static class XEditorUtils
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static string MakeLibraryPath(string name)
    {
        var dataPath = System.IO.Path.GetFullPath(".");
        dataPath = dataPath.Replace("\\", "/");
        dataPath += "/Library/" + name + ".dat";

        return dataPath;
    }

    /// <summary>
    /// Marks current active scene dirty AND save.
    /// </summary>
    public static void MarkCurrentSceneDirty()
    {
        UnityEngine.SceneManagement.Scene scene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene();
        if (scene.IsValid())
        {
            UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene);
            UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene);
        }
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    /// <summary>
    /// Get list of gameobjects under parent gameobject(include self) which have type T inherited from Component 
    /// </summary>
    public static List<GameObject> GetGameObjectsHaveComponent<T>(GameObject parent) where T : Component
    {
        List<GameObject> gos = new List<GameObject>();
        if (parent.GetComponent<T>() != null)
            gos.Add(parent);
        for (int i = 0; i < parent.transform.childCount; ++i)
        {
            gos.AddRange(GetGameObjectsHaveComponent<T>(parent.transform.GetChild(i).gameObject));
        }
        return gos;
    }

    /// <summary>
    /// Write serializeable datas to Json file.
    /// </summary>
    /// <param name="datas">serializeable datas.</param>
    /// <param name="path">whole path, include subfix.</param>
    public static void WriteToFile(object datas, string path, System.Action onComplete = null)
    {
        System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Create, System.IO.FileAccess.Write);
        if (fs != null)
        {
            StringBuilder sb = new StringBuilder();
            System.IO.StringWriter writer = new System.IO.StringWriter(sb);
            LitJson.JsonMapper.ToJson(datas,
                new LitJson.JsonWriter(writer)
                {
                    PrettyPrint = true
                });

            byte[] buff = Encoding.UTF8.GetBytes(sb.ToString());
            fs.Write(buff, 0, buff.Length);
            fs.Close();
        }

        if (onComplete != null)
            onComplete();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="folderPath"></param>
    /// <param name="allDir"></param>
    /// <param name="fix"></param>
    /// <returns></returns>
    public static List<string> FindFolder(string folderPath, bool allDir = true, string fix = "*.prefab")
    {
        string fullPath = Path.Combine(Application.dataPath, folderPath);
        string[] names = Directory.GetFiles(fullPath, fix,
            allDir ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

        List<string> fileNames = new List<string>();

        int discardeIndex = Application.dataPath.Length + 1;
        if (names != null && names.Length > 0)
        {
            for (int i = 0; i < names.Length; i++)
            {
                names[i] = names[i].Substring(discardeIndex, names[i].Length - discardeIndex);
                names[i] = names[i].Replace("\\", "/");

                fileNames.Add(Path.Combine(XDirectory.Assets.ToString(), names[i]).Replace("\\", "/"));
            }
        }

        return fileNames;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="path"></param>
    /// <param name="all"></param>
    /// <param name="fix"></param>
    /// <returns></returns>
    public static List<string> GetFolder(string path, bool all = true, string fix = "*.prefab")
    {
        string[] names = Directory.GetFiles(path, fix,
            all ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

        List<string> fileNames = new List<string>();
        for (int i = 0; i < names.Length; i++)
        {
            names[i] = names[i].Replace("\\", "/");
            string file = names[i].Replace(Application.dataPath, "Assets");
        }

        return fileNames;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="folderPath"></param>
    /// <param name="isAllDir"></param>
    /// <param name="fileFix"></param>
    /// <returns></returns>
    public static List<string> GetAssetPathInFolder(string folderPath, bool isAllDir = true, string fileFix = "*.prefab")
    {
        string fullPath = Path.Combine(Application.dataPath, folderPath);
        string[] names = Directory.GetFiles(fullPath, fileFix,
            isAllDir ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

        List<string> fileNames = new List<string>();
        int discardeIndex = Application.dataPath.Length + 1;
        if (names != null && names.Length > 0)
        {
            for (int i = 0; i < names.Length; i++)
            {
                int length = names[i].Length - discardeIndex;
                names[i] = names[i].Substring(discardeIndex, length);
                names[i] = names[i].Replace("\\", "/");

                fileNames.Add(Path.Combine(XDirectory.Assets.ToString(), names[i]));
            }
        }
        return fileNames;
    }
}